package com.j256.ormlite.hmos;

import com.j256.ormlite.db.DatabaseType;
import com.j256.ormlite.db.SqlLiteHarmonyDatabaseType;
import com.j256.ormlite.hmos.apptools.OrmLiteRdbOpenHelper;
import com.j256.ormlite.logger.Logger;
import com.j256.ormlite.logger.LoggerFactory;
import com.j256.ormlite.support.BaseConnectionSource;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.support.DatabaseConnection;
import com.j256.ormlite.support.DatabaseConnectionProxyFactory;
import ohos.data.rdb.RdbOpenCallback;
import ohos.data.rdb.RdbStore;
import ohos.data.rdb.StoreConfig;

import java.sql.SQLException;

/**
 * HmosDatabaseConnection
 *
 */
public class HmosConnectionSource extends BaseConnectionSource implements ConnectionSource {
    private static DatabaseConnectionProxyFactory connectionProxyFactory;
    private static final Logger logger = LoggerFactory.getLogger(HmosConnectionSource.class);
    private final DatabaseType databaseType = new SqlLiteHarmonyDatabaseType();

    private final OrmLiteRdbOpenHelper helper;
    private RdbStore rdbDatabase;
    private DatabaseConnection connection = null;
    private volatile boolean isOpen = true;

    private boolean isCancelQueriesEnabled = false;

    private String databaseName;
    private String databaseAlias;
    private int databaseVersion;

    private StoreConfig stConfig = null;

    /**
     * Return whether this connection is read-write or not (real-only).
     *
     * @param helper OrmLiteRdbOpenHelper
     */
    public HmosConnectionSource(OrmLiteRdbOpenHelper helper) {
        this.helper = helper;
        this.rdbDatabase = null;
        this.databaseAlias = helper.databaseAlias;
        this.databaseName = helper.databaseName;
        this.databaseVersion = helper.databaseVersion;
    }

    /**
     * Return whether this connection is read-write or not (real-only).
     *
     * @param rdbDatabase RdbStore
     */
    public HmosConnectionSource(RdbStore rdbDatabase) {
        this.helper = null;
        this.rdbDatabase = rdbDatabase;
    }

    @Override
    public DatabaseConnection getReadOnlyConnection(String tableName) throws SQLException {
        return getReadWriteConnection(tableName);
    }

    @Override
    public DatabaseConnection getReadWriteConnection(String tableName) throws SQLException {
        DatabaseConnection conn = getSavedConnection();
        if (conn != null) {
            return conn;
        }
        if (connection == null) {
            RdbStore db;
            if (rdbDatabase == null) {
                StoreConfig config = StoreConfig.newDefaultConfig(databaseName);
                RdbOpenCallback callback = new RdbOpenCallback() {
                    @Override
                    public void onCreate(RdbStore store) {
                    }

                    @Override
                    public void onUpgrade(RdbStore store, int oldVersion, int newVersion) {
                    }
                };
                db = helper.getRdbStore(config, databaseVersion, callback, null);
            } else {
                db = rdbDatabase;
            }

            connection = new HmosDatabaseConnection(db, true, isCancelQueriesEnabled);

            helper.onCreate(db, helper.connectionSource);

            if (connectionProxyFactory != null) {
                connection = connectionProxyFactory.createProxy(connection);
            }
            logger.trace("created connection {} for db {}, helper {}", connection, db, helper);
        } else {
            logger.trace("{}: returning read-write connection {}, helper {}", this, connection, helper);
        }

        return connection;
    }

    @Override
    public void releaseConnection(DatabaseConnection databaseConnection) {
    }

    @Override
    public boolean saveSpecialConnection(DatabaseConnection databaseConnection) throws SQLException {
        return saveSpecial(databaseConnection);
    }

    @Override
    public void clearSpecialConnection(DatabaseConnection databaseConnection) {
        clearSpecial(databaseConnection, logger);
    }

    @Override
    public void close() {
        isOpen = false;
    }

    @Override
    public void closeQuietly() {
        close();
    }

    @Override
    public DatabaseType getDatabaseType() {
        return databaseType;
    }

    @Override
    public boolean isOpen(String tableName) {
        return isOpen;
    }

    @Override
    public boolean isSingleConnection(String tableName) {
        return true;
    }

    /**
     * Set to enable connection proxying. Set to null to disable.
     *
     * @param databaseConnectionProxyFactory DatabaseConnectionProxyFactory
     */
    public static void setDatabaseConnectionProxyFactory(
    		DatabaseConnectionProxyFactory databaseConnectionProxyFactory) {
        HmosConnectionSource.connectionProxyFactory = databaseConnectionProxyFactory;
    }

    public boolean isCancelQueriesEnabled() {
        return isCancelQueriesEnabled;
    }

    public void setCancelQueriesEnabled(boolean iscancelQueriesEnabled) {
        this.isCancelQueriesEnabled = iscancelQueriesEnabled;
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + "@" + Integer.toHexString(super.hashCode());
    }
}
